package com.padakeji.android.ui.widget;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by atanl on 2015/10/22.
 *
 * 官方RecyclerView的加强版
 * 加入添加header和footer的功能
 *
 */
public class RecyclerViewX extends RecyclerView {

    // 抄自google的HeaderGridView。
    private static class FixedViewInfo {
        /**
         * The view to add to the grid
         */
        public View view;

        public ViewGroup viewContainer;
        /**
         * The data backing the view.
         */
        public Object data;
        /**
         * <code>true</code> if the fixed view should be selectable in the grid
         */
        public boolean isSelectable;
    }

    public interface OnItemClickListener {
        void onItemClick(RecyclerViewX recyclerViewX, View view, int position, long id);
    }

    OnItemClickListener mOnItemClickListener;

    public void setOnItemClickListener(OnItemClickListener l) {
        this.mOnItemClickListener = l;
    }

    private ArrayList<FixedViewInfo> tempHeaderViewInfos = new ArrayList<>();
    private ArrayList<FixedViewInfo> tempFooterViewInfos = new ArrayList<>();

    private Adapter mAdapter;

    public int getHeaderCount() {
        return mAdapter == null ? 0 : mAdapter.headerViewInfos.size();
    }

    public int getFooterCount() {
        return mAdapter == null ? 0 : mAdapter.footerViewInfos.size();
    }

    public void addHeaderView(View view) {
        FixedViewInfo info = new FixedViewInfo();
        info.view = view;
        if (mAdapter == null) {
            tempFooterViewInfos.add(info);
        } else {
            mAdapter.headerViewInfos.add(info);
            mAdapter.notifyDataSetChanged();
        }
    }

    public void removeHeaderView(View v) {
        if (mAdapter == null) {
            removeFixedViewFrom(tempHeaderViewInfos, v);
        } else {
            removeFixedViewFrom(mAdapter.headerViewInfos, v);
        }
        mAdapter.notifyDataSetChanged();
    }

    public void clearHeaderViews() {
        if (mAdapter == null) {
            tempHeaderViewInfos.clear();
        } else {
            mAdapter.headerViewInfos.clear();
            mAdapter.notifyDataSetChanged();
        }
    }


    public void addFooterView(View view) {
        FixedViewInfo info = new FixedViewInfo();
        info.view = view;
        if (mAdapter == null) {
            tempFooterViewInfos.add(info);
        } else {
            mAdapter.footerViewInfos.add(info);
            mAdapter.notifyDataSetChanged();
        }
    }

    public void removeFooterView(View v) {
        if (mAdapter == null) {
            removeFixedViewFrom(tempFooterViewInfos, v);
        } else {
            removeFixedViewFrom(mAdapter.footerViewInfos, v);
            mAdapter.notifyDataSetChanged();
        }
    }

    private void removeFixedViewFrom(List<FixedViewInfo> infos, View v) {
        int i, size = infos.size();
        for (i = 0; i < size; ++i) {
            FixedViewInfo info = infos.get(i);
            if (info.view == v) {
                infos.remove(i);
                break;
            }
        }
    }

    public void clearFooterViews() {
        if (mAdapter == null) {
            tempFooterViewInfos.clear();
        } else {
            mAdapter.footerViewInfos.clear();
            mAdapter.notifyDataSetChanged();
        }
    }

    @Override
    public final void setAdapter(RecyclerView.Adapter adapter) {
        throw new RuntimeException("Please use setAdapter(RecyclerViewX.Adapter) instead.");
    }

    public void setAdapter(Adapter adapter) {
        if (mAdapter != null) {
            tempHeaderViewInfos.addAll(mAdapter.headerViewInfos);
            tempFooterViewInfos.addAll(mAdapter.footerViewInfos);
        }
        mAdapter = adapter;
        if (mAdapter != null) {
            mAdapter.headerViewInfos.addAll(tempHeaderViewInfos);
            mAdapter.footerViewInfos.addAll(tempFooterViewInfos);
            tempHeaderViewInfos.clear();
            tempFooterViewInfos.clear();
            mAdapter.setAttachedRecycler(this);
        }
        super.setAdapter(mAdapter);
    }

    /**
     * Retrieves the previously set adapter or null if no adapter is set.
     *
     * @return The previously set adapter
     * @see #setAdapter(Adapter)
     */
    @Override
    public Adapter getAdapter() {
        return mAdapter;
    }

    public RecyclerViewX(Context context) {
        super(context);
        init();
    }

    public RecyclerViewX(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RecyclerViewX(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {

    }

    public abstract static class Adapter extends RecyclerView.Adapter {

        private static final int VIEW_TYPE_HEADER = -1;
        private static final int VIEW_TYPE_FOOTER = -2;

        protected Context mContext;
        RecyclerViewX mAttachedRecycler;
        ArrayList<FixedViewInfo> headerViewInfos = new ArrayList<>();
        ArrayList<FixedViewInfo> footerViewInfos = new ArrayList<>();

        void setAttachedRecycler(RecyclerViewX attachedRecycler) {
            this.mAttachedRecycler = attachedRecycler;
            this.mContext = attachedRecycler.getContext();
        }

        int getHeaderCount() {
            return headerViewInfos.size();
        }

        int getFooterCount() {
            return footerViewInfos.size();
        }

        public Adapter(Context context) {
            if (context == null) {
                throw new RuntimeException("A context must be passed as parameter.");
            }
            this.mContext = context;
        }

        public Adapter() {}

        @Override
        public final int getItemViewType(int position) {
            if (position >= 0 && position < headerViewInfos.size()) {
                return VIEW_TYPE_HEADER;
            } else if (position >= getItemCount() - footerViewInfos.size() && position < getItemCount()) {
                return VIEW_TYPE_FOOTER;
            } else {
                return itemViewType(position - headerViewInfos.size());
            }
        }

        /**
         * 请不要返回 -1 和 -2。这两种类型已经被占用。
         * @param position
         * @return
         */
        public int itemViewType(int position) {
            return super.getItemViewType(position);
        }

        @Override
        public final RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            switch (viewType) {
                case VIEW_TYPE_HEADER:
                    return new HeaderAndFooterViewHolder(mContext);
                case VIEW_TYPE_FOOTER:
                    return new HeaderAndFooterViewHolder(mContext);
                default:
                    return onCreateItemViewHolder(parent, viewType);
            }
        }

        public abstract RecyclerView.ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType);

        @Override
        public final void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
            switch (getItemViewType(position)) {
                case VIEW_TYPE_HEADER:
                    ViewGroup headerContainer = (ViewGroup)holder.itemView;
                    headerContainer.removeAllViews();
                    headerContainer.addView(headerViewInfos.get(position).view);
                    break;
                case VIEW_TYPE_FOOTER:
                    ViewGroup footerContainer = (ViewGroup)holder.itemView;
                    footerContainer.removeAllViews();
                    footerContainer.addView(footerViewInfos.get(footerViewInfos.size() - getItemCount() + position).view);
                    break;
                default:
                    holder.itemView.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (mAttachedRecycler.mOnItemClickListener != null) {
                                mAttachedRecycler.mOnItemClickListener.onItemClick(mAttachedRecycler, holder.itemView, position, getItemId(position));
                            }
                        }
                    });
                    onBindItemViewHolder(holder, position - headerViewInfos.size());
                    break;
            }
        }

        public abstract void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position);

        @Override
        public final int getItemCount() {
            return itemCount() + headerViewInfos.size() + footerViewInfos.size();
        }

        public abstract int itemCount();

    }

    private static class HeaderAndFooterViewHolder extends RecyclerView.ViewHolder {
        HeaderAndFooterViewHolder(@NonNull Context context) {
            super(new FrameLayout(context));
            LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            super.itemView.setLayoutParams(params);
        }
    }

}
